import { Injectable, NotFoundException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { DiscussionPost } from './entities/discussion-post.entity';
import { CreateDiscussionPostDto } from './dto/create-discussion-post.dto';
import { UpdateDiscussionPostDto } from './dto/update-discussion-post.dto';
import { PostResponseDto } from './dto/post-response.dto';

@Injectable()
export class DiscussionPostService {
  constructor(
    @InjectRepository(DiscussionPost)
    private discussionPostRepository: Repository<DiscussionPost>,
  ) {}

  async create(createDiscussionPostDto: CreateDiscussionPostDto): Promise<PostResponseDto> {
    try {
      console.log('Creating post with author ID:', createDiscussionPostDto.authorId);
      
      // Try to check if the author exists, but don't block post creation if it fails
      // This is for development/testing to avoid frustration
      let authorExists = false;
      
      // Method 1: Direct query
      try {
        const result = await this.discussionPostRepository.manager
          .createQueryBuilder()
          .select('id')
          .from('apartment_users', 'au')
          .where('id = :id', { id: createDiscussionPostDto.authorId })
          .getRawOne();
          
        if (result) {
          authorExists = true;
          console.log('Author found via direct query');
        }
      } catch (error) {
        console.error('Error checking author with direct query:', error.message);
      }
      
      // Method 2: Using repository if method 1 failed
      if (!authorExists) {
        try {
          const userRepository = this.discussionPostRepository.manager.getRepository('ApartmentUser');
          const user = await userRepository.findOne({ where: { id: createDiscussionPostDto.authorId } });
          if (user) {
            authorExists = true;
            console.log('Author found via repository');
          }
        } catch (error) {
          console.error('Error checking author with repository:', error.message);
        }
      }
      
      // Just log a warning if author doesn't exist but proceed anyway (for development)
      if (!authorExists) {
        console.warn(`Warning: Author with ID "${createDiscussionPostDto.authorId}" not found, but proceeding with post creation anyway.`);
      }

      // Create and save the post
      const discussionPost = this.discussionPostRepository.create({
        ...createDiscussionPostDto,
        viewCount: 0,
        commentCount: 0,
        likeCount: 0,
        isHidden: false
      });
      
      const savedPost = await this.discussionPostRepository.save(discussionPost);
      
      // Load the post with author relation to return complete data
      try {
        const postWithAuthor = await this.findOne(savedPost.id);
        return PostResponseDto.fromEntity(postWithAuthor);
      } catch (error) {
        // If loading with author fails, just return a basic response
        console.error('Error loading post with author, returning basic response:', error.message);
        return PostResponseDto.fromEntity(savedPost, false);
      }
    } catch (error) {
      // Log the detailed error for debugging
      console.error('Error creating discussion post:', error);
      
      // Rethrow to maintain the original error
      throw error;
    }
  }

  async findAll(): Promise<PostResponseDto[]> {
    const posts = await this.discussionPostRepository.find({
      relations: ['author'],
      order: { createdAt: 'DESC' },
    });
    
    return posts.map(post => PostResponseDto.fromEntity(post));
  }

  async findAllVisible(): Promise<PostResponseDto[]> {
    const posts = await this.discussionPostRepository.find({
      where: { isHidden: false },
      relations: ['author'],
      order: { createdAt: 'DESC' },
    });
    
    return posts.map(post => PostResponseDto.fromEntity(post));
  }

  async findOne(id: string): Promise<DiscussionPost> {
    const post = await this.discussionPostRepository.findOne({
      where: { id },
      relations: ['author'],
    });
    
    if (!post) {
      throw new NotFoundException(`Discussion post with ID "${id}" not found`);
    }
    
    // Increment view count
    post.viewCount += 1;
    await this.discussionPostRepository.save(post);
    
    return post;
  }

  async findOneFormatted(id: string): Promise<PostResponseDto> {
    const post = await this.findOne(id);
    return PostResponseDto.fromEntity(post);
  }

  async update(id: string, updateDiscussionPostDto: UpdateDiscussionPostDto): Promise<PostResponseDto> {
    const post = await this.findOne(id);
    
    // Update the post with new data
    Object.assign(post, updateDiscussionPostDto);
    const updatedPost = await this.discussionPostRepository.save(post);
    
    return PostResponseDto.fromEntity(updatedPost);
  }

  async remove(id: string): Promise<void> {
    const result = await this.discussionPostRepository.delete(id);
    
    if (result.affected === 0) {
      throw new NotFoundException(`Discussion post with ID "${id}" not found`);
    }
  }

  async likePost(id: string): Promise<DiscussionPost> {
    const post = await this.discussionPostRepository.findOne({
      where: { id },
      relations: ['author'],
    });
    
    if (!post) {
      throw new NotFoundException(`Discussion post with ID "${id}" not found`);
    }
    
    // Increment like count
    post.likeCount += 1;
    return await this.discussionPostRepository.save(post);
  }

  /**
   * Find all posts by a specific author ID
   */
  async findByAuthorId(authorId: string): Promise<PostResponseDto[]> {
    const posts = await this.discussionPostRepository.find({
      where: { authorId },
      relations: ['author'],
      order: { createdAt: 'DESC' },
    });
    
    return posts.map(post => PostResponseDto.fromEntity(post));
  }
} 